package com.xwaf.platform.web.config;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;

import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * 
 * <p>
 * 接口可视化
 * <p>
 * 
 * @author 李聪 <br>
 * @email xwaf_love@yeah.net <br>
 * @since JDK 1.8<br>
 * @date 2019年12月30日 上午9:23:42 <br>
 * @see 无<br>
 *      Copyright (c) 2019, xwaf_love@yeah.net All Rights Reserved.<br>
 */
@Configuration
@EnableSwagger2
public class SwaggerConfig {

	// 定义分隔符,配置Swagger多包
	private static final String SPLITOR = ";";
	// 模块目录
	private static final String AUTH = "com.xwaf.platform.web.controller.auth";
	private static final String GATEWAY = "com.xwaf.platform.web.controller.gateway";
	private static final String PAY = "com.xwaf.platform.web.controller.pay";

	@Bean
	public Docket auth() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("权限API接口文档").select()//
				// .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
				.apis(basePackage(AUTH))//
				.paths(PathSelectors.any())//
				.build()//
				// .directModelSubstitute(LocalDate.class, String.class)
				.useDefaultResponseMessages(false)//
				// .securitySchemes(securitySchemes())
				// .securityContexts(securityContexts())
				.apiInfo(apiInfo()).securitySchemes(securitySchemes());
	}

	@Bean
	public Docket gateway() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("网关API接口文档").select()//
				.apis(basePackage(GATEWAY))//
				.paths(PathSelectors.any())//
				.build()//
				.useDefaultResponseMessages(false)//
				.apiInfo(apiInfo());
	}

	@Bean
	public Docket pay() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("支付API接口文档").select()//
				.apis(basePackage(PAY))//
				.paths(PathSelectors.any())//
				.build()//
				.useDefaultResponseMessages(false)//
				.apiInfo(apiInfo());
	}

	private ApiInfo apiInfo() {
		return new ApiInfoBuilder()//
				.title("平台")//
				.description("API 文档")//
				.contact(new Contact("lic", "https://gitee.com/xwaf/projects", "xwaf_love@yeah.net"))
				.termsOfServiceUrl("https://gitee.com/xwaf/projects").version("1.0")//
				.build();
	}

	/**
	 * 重写basePackage方法
	 */
	public static Predicate<RequestHandler> basePackage(final String basePackage) {
		return input -> declaringClass(input).transform(handlerPackage(basePackage)).or(true);
	}

	private static Function<Class<?>, Boolean> handlerPackage(final String basePackage) {
		return input -> {
			// 循环判断匹配
			for (String strPackage : basePackage.split(SPLITOR)) {
				boolean isMatch = input.getPackage().getName().startsWith(strPackage);
				if (isMatch) {
					return true;
				}
			}
			return false;
		};
	}

	private static Optional<? extends Class<?>> declaringClass(RequestHandler input) {
		// return Optional.fromNullable(input.declaringClass());
		return Optional.fromNullable(input.getHandlerMethod().getMethod().getDeclaringClass());
	}

	private List<ApiKey> securitySchemes() {
		List<ApiKey> apiKeys = new ArrayList<>();
		apiKeys.add(new ApiKey("Authorization", "accessToken", "header"));
		return apiKeys;
	}

	private List<SecurityContext> securityContexts() {
		List<SecurityContext> securityContexts = new ArrayList<>();
		securityContexts.add(SecurityContext.builder().securityReferences(defaultAuth())
				.forPaths(PathSelectors.regex("^(?!auth).*$")).build());
		return securityContexts;
	}

	private List<SecurityReference> defaultAuth() {
		AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
		AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
		authorizationScopes[0] = authorizationScope;
		List<SecurityReference> securityReferences = new ArrayList<>();
		securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
		return securityReferences;
	}
}
